package quarto.view.client;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import javax.swing.border.EmptyBorder;
import quarto.Message;
import quarto.controller.Protocol;
import quarto.controller.client.Client;
import quarto.controller.client.strategy.Strategy;

/**
 * Dialoog die de gegevens opvraagt met betrekking tot de client connectie
 * @knows
 * - ClientGUI
 * @does
 * - Gegevens vragen om mee te verbinden
 * @author Frank Borgonjen & Tim Smit
 */

public class ClientConnectionDialog extends JDialog implements ActionListener
{
    /** menselijke speler */
    public static final String HUMAN_PLAYER    = "Menslijke speler";
    
    /** computer speler */
    public static final String COMPUTER_PLAYER = "Computer speler";
    
    /** tekstveld voor de gebruikersnaam */
    private JTextField  TFUsername;
    
    /** tekstveld voor het host adres */
    private JTextField  TFAddress;
    
    /** tekstveld voor de poort */
    private JTextField  TFPort;
    
    /** combobox voor het type speler */
    private JComboBox   CBPlayerType;
    
    /** slider voor de strategie */
    private JComboBox   CBStrategy;
    
    /** label voor een foutmelding */
    private JLabel      LError;
    
    /** knop om te connecten */
    private JButton     BConnect;
    
    /** zijn we aan het connecten */
    private boolean     connect;
    
    /** het parent object, de gui */
    private ClientGUI   parent;
    
    /** lijst met beschikbare strategieen */
    private ArrayList<Strategy> strategies;
    
    /**
     * Maakt een nieuw connectie dialoog aan
     */
    public ClientConnectionDialog(JFrame parent)
    {
        super(parent, Message.DIALOG_TITLE, true);
        this.parent = (ClientGUI) parent;
        this.buildDialog();
    }
    
    /**
     * Bouwt het dialoog op met swing componenten.
     */
    private void buildDialog() 
    {
        // we zijn nog niet aan het connecten
        this.connect = false;
        
        this.setSize(310, 210);
        this.setLocationRelativeTo(null);
        this.setLayout(new FlowLayout());
        this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        
        JPanel p = new JPanel(new GridLayout(6,2));
        p.setBorder(new EmptyBorder(5, 5, 5, 5));
        
        // het type speler
        JLabel LBPlayerType = new JLabel(Message.DIALOG_KIND_OF_PLAYER + ":");
        this.CBPlayerType = new JComboBox(new String[] {HUMAN_PLAYER, COMPUTER_PLAYER});
        this.CBPlayerType.addActionListener(this);
        p.add(LBPlayerType);
        p.add(this.CBPlayerType);
        
        // strategieen
        JLabel LBStrategy = new JLabel(Message.DIALOG_STRATEGY + ":");
        this.CBStrategy = new JComboBox();
        this.strategies = this.parent.getStrategies();
        for (Strategy strategy : strategies)
        {
            this.CBStrategy.addItem(strategy.getName());
        }
        this.CBStrategy.setEnabled(false);
        
        p.add(LBStrategy);
        p.add(this.CBStrategy);
        
        // de gebruikersnaam
        JLabel LBUsername = new JLabel(Message.DIALOG_NAME + ":");
        this.TFUsername = new JTextField(Message.DIALOG_NAME_VALUE);
        p.add(LBUsername);
        p.add(this.TFUsername);
        
        // het poort nummer
        JLabel LBPort = new JLabel(Message.DIALOG_PORT + ":");
        this.TFPort = new JTextField(Message.DIALOG_PORT_VALUE);
        p.add(LBPort);
        p.add(this.TFPort);
        
        // het host adres
        JLabel LBAddress = new JLabel(Message.DIALOG_HOST + ":");
        this.TFAddress = new JTextField(getHostAddress());
        p.add(LBAddress);
        p.add(this.TFAddress);     
        
        // de verbindknop
        this.LError = new JLabel();
        this.BConnect = new JButton(Message.DIALOG_CONNECT);
        this.BConnect.addActionListener(this);
        p.add(this.LError);
        p.add(this.BConnect);
        
        Container c = this.getContentPane();
        c.add(p);
        
        // gedrag van het afsluiten van het dialoog
        this.addWindowListener(new WindowAdapter() 
        {
            @Override
            public void windowClosing(WindowEvent e) 
            {
                if (!parent.isGUIStarted())
                {
                    // sluit de boel af
                    System.exit(0);
                }
                else
                {
                    dispose();
                }
            }
        });
    }

    /**
     * Voert de acties uit die horen bij bepaalde acties, het verbinden
     * en wijzigen van het type speler
     * @param e
     */
    public void actionPerformed(ActionEvent e) 
    {
        Object source = e.getSource();

        // de actie komt van de speler switch
        if (source == CBPlayerType)
        {
            // stratgieen wel al dan niet beschikbaar maken
            CBStrategy.setEnabled(!getPlayerType().equals(Client.HUMAN));
        }
        // als alle velden niet leeg zijn
        else if (this.validateFields())
        {
            // laat het dialoog verdwijnen
            this.dispose();

            // laten weten dat we proberen te connecten
            this.connect = true;
        }
        else
        {
            this.LError.setText(Message.DIALOG_ERROR);
        }
    }
    
    /**
     * Controleert of er in alle velden iets is ingevuld
     * @return 
     */
    public boolean validateFields()
    {
        return (this.getUsername().matches("^([^" + Protocol.DELIM + "]+)$") && 
                !this.getAddress().equals("") && 
                this.getPort().matches("^([0-9]+)$"));
    }
    
    /**
     * Moet er een poging gedaan worden om een verbinding te starten
     * @return verbindpoging
     */
    public boolean tryToConnect()
    {
        return this.connect;
    }
    
    /**
     * Geeft het type van de speler terug
     * @return type speler, #Client.HUMAN | #Client.HUMAN
     */
    public String getPlayerType()
    {
        String item_value = this.CBPlayerType.getSelectedItem().toString();
        return (item_value.equals(HUMAN_PLAYER)) ? Client.HUMAN : Client.COMPUTER;
    }
    
    /**
     * geeft de index van de strategie terug
     * @return index van strategie
     */
    public int getStrategy()
    {
        return this.CBStrategy.getSelectedIndex();
    }
    
    /**
     * Retourneert de gebruikersnaam
     * @return username
     */
    public String getUsername()
    {
        return this.TFUsername.getText();
    }
    
    /**
     * Geeft het serveradres terug waarop verbonden moet worden
     * @return hostadres
     */
    public String getAddress()
    {
        return this.TFAddress.getText();
    }
    
    /**
     * De poort waarop verbonden moet worden
     * @return
     */
    public String getPort()
    {
        return this.TFPort.getText();
    }
    
    /** Levert het Internetadres van deze computer op. */
    private String getHostAddress()
    {
        try
        {
            InetAddress iaddr = InetAddress.getLocalHost();
            return iaddr.getHostAddress();
        }
        catch (UnknownHostException e)
        {
            return "?unknown?";
        }
    }
}
